home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / OpenGL / OPENGL2.EXE / _SETUP.1 / indextex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-21  |  14.9 KB  |  595 lines

  1. /*
  2. ** Color Index Texture Example
  3. */
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <windows.h>
  8. #include <GL/gl.h>
  9.  
  10. #if !defined(M_PI)
  11. #define M_PI 3.14159265F
  12. #endif
  13.  
  14. char *className = "OpenGL";
  15. char *windowName = "Color Index Texture";
  16. int winX = 0, winY = 0;
  17. int winWidth = 300, winHeight = 300;
  18.  
  19. HDC hDC;
  20. HGLRC hGLRC;
  21. HPALETTE hPalette;
  22.  
  23. void (*idleFunc)(void);
  24.  
  25. /* Struct used to manage color ramps */
  26. struct colorIndexState {
  27.     GLfloat amb[3];    /* ambient color / bottom of ramp */
  28.     GLfloat diff[3];    /* diffuse color / middle of ramp */
  29.     GLfloat spec[3];    /* specular color / top of ramp */
  30.     GLfloat ratio;    /* ratio of diffuse to specular in ramp */
  31.     GLint indexes[3];    /* where ramp was placed in palette */
  32. };
  33.  
  34. /*
  35. ** Each entry in this array corresponds to a color ramp in the
  36. ** palette.  The indexes member of each struct is updated to
  37. ** reflect the placement of the color ramp in the palette.
  38. */
  39. #define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))
  40. struct colorIndexState colors[] = {
  41.     {
  42.         { 0.0F, 0.0F, 0.0F },
  43.         { 0.1F, 0.6F, 0.3F },
  44.         { 1.0F, 1.0F, 1.0F },
  45.         0.75F, { 0, 0, 0 },
  46.     },
  47.     {
  48.         { 0.0F, 0.0F, 0.0F },
  49.         { 0.0F, 0.2F, 0.5F },
  50.         { 1.0F, 1.0F, 1.0F },
  51.         0.75F, { 0, 0, 0 },
  52.     },
  53.     {
  54.         { 0.0F, 0.05F, 0.05F },
  55.         { 0.6F, 0.0F, 0.8F },
  56.         { 1.0F, 1.0F, 1.0F },
  57.         0.75F, { 0, 0, 0 },
  58.     },
  59. };
  60.  
  61. static GLboolean
  62. checkExtension(const char *name)
  63. {
  64.     const char *p = (const char *) glGetString(GL_EXTENSIONS);
  65.  
  66.     while (p = strstr(p, name)) {
  67.     const char *q = p + strlen(name);
  68.  
  69.     if (*q == ' ' || *q == '\0') {
  70.         return GL_TRUE;
  71.     }
  72.     p = q;
  73.     }
  74.     return GL_FALSE;
  75. }
  76.  
  77. void
  78. drawTorus(void)
  79. {
  80.     int numMajor = 32;
  81.     int numMinor = 24;
  82.     float majorRadius = 0.6F;
  83.     float minorRadius = 0.2F;
  84.     double majorStep = 2.0F*M_PI / numMajor;
  85.     double minorStep = 2.0F*M_PI / numMinor;
  86.     int i, j;
  87.  
  88.     for (i=0; i<numMajor; ++i) {
  89.     double a0 = i * majorStep;
  90.     double a1 = a0 + majorStep;
  91.     GLfloat x0 = (GLfloat) cos(a0);
  92.     GLfloat y0 = (GLfloat) sin(a0);
  93.     GLfloat x1 = (GLfloat) cos(a1);
  94.     GLfloat y1 = (GLfloat) sin(a1);
  95.  
  96.     glBegin(GL_TRIANGLE_STRIP);
  97.     for (j=0; j<=numMinor; ++j) {
  98.         double b = j * minorStep;
  99.         GLfloat c = (GLfloat) cos(b);
  100.         GLfloat r = minorRadius * c + majorRadius;
  101.         GLfloat z = minorRadius * (GLfloat) sin(b);
  102.  
  103.         glNormal3f(x0*c, y0*c, z/minorRadius);
  104.         glTexCoord2f(i/(GLfloat) numMajor, j/(GLfloat) numMinor);
  105.         glVertex3f(x0*r, y0*r, z);
  106.  
  107.         glNormal3f(x1*c, y1*c, z/minorRadius);
  108.         glTexCoord2f((i+1)/(GLfloat) numMajor, j/(GLfloat) numMinor);
  109.         glVertex3f(x1*r, y1*r, z);
  110.     }
  111.     glEnd();
  112.     }
  113. }
  114.  
  115. void
  116. setCheckTexture(void)
  117. {
  118.     BOOL textureReplaceEnv = FALSE;
  119.     int texWidth = 64;
  120.     int texHeight = 64;
  121.     GLubyte *texPixels, *p;
  122.     int texSize;
  123.     int i, j;
  124.  
  125.     texSize = texWidth*texHeight*1*sizeof(GLubyte);
  126.     if (textureReplaceEnv) {
  127.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  128.     } else {
  129.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
  130.     }
  131.  
  132.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  133.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  134.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  135.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  136.  
  137.     texPixels = (GLubyte *) malloc(texSize);
  138.     if (texPixels == NULL) {
  139.     return;
  140.     }
  141.  
  142.     p = texPixels;
  143.     for (i=0; i<texHeight; ++i) {
  144.     for (j=0; j<texWidth; ++j) {
  145.         int rampIndex = textureReplaceEnv ? 1 : 0;
  146.         if ((i ^ j) & 4) {
  147.         *p = colors[0].indexes[rampIndex] & 0xff;
  148.         } else {
  149.         *p = colors[1].indexes[rampIndex] & 0xff;
  150.         }
  151.         p += 1;
  152.     }
  153.     }
  154.  
  155.     glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
  156.          texWidth, texHeight, 0,
  157.          GL_COLOR_INDEX, GL_UNSIGNED_BYTE, texPixels);
  158.  
  159.     free(texPixels);
  160. }
  161.  
  162. /*****************************************************************/
  163.  
  164. void
  165. setProjection(void)
  166. {
  167.     glMatrixMode(GL_PROJECTION);
  168.     glLoadIdentity();
  169.     /*
  170.     ** Preserve the aspect ratio of objects in the scene.
  171.     */
  172.     if (winWidth > winHeight) {
  173.     GLfloat aspect = (GLfloat) winWidth / (GLfloat) winHeight;
  174.     glFrustum(-0.5F*aspect, 0.5F*aspect, -0.5F, 0.5F, 1.0F, 3.0F);
  175.     } else {
  176.     GLfloat aspect = (GLfloat) winHeight / (GLfloat) winWidth;
  177.     glFrustum(-0.5F, 0.5F, -0.5F*aspect, 0.5F*aspect, 1.0F, 3.0F);
  178.     }
  179.     glMatrixMode(GL_MODELVIEW);
  180. }
  181.  
  182. void
  183. init(void)
  184. {
  185.     GLfloat matDiff[4] = { 0.65F, 0.05F, 0.20F, 0.60F };
  186.     GLfloat matSpec[4] = { 0.50F, 0.50F, 0.50F, 1.00F };
  187.     GLfloat matShine = 20.00F;
  188.     GLint indexes[3];
  189.     GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F };
  190.  
  191.     glClearColor(colors[2].diff[0], colors[2].diff[1], colors[2].diff[2], 1.0F);
  192.     glClearIndex((GLfloat) colors[2].indexes[1]);
  193.  
  194.     setProjection();
  195.     glTranslatef(0.0F, 0.0F, -2.0F);
  196.  
  197.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
  198.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
  199.     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
  200.  
  201.     indexes[0] = 0;
  202.     indexes[1] = colors[0].indexes[1] - colors[0].indexes[0];
  203.     indexes[2] = colors[0].indexes[2] - colors[0].indexes[0];
  204.     glMaterialiv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, indexes);
  205.     glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  206.     glEnable(GL_LIGHT0);
  207.  
  208.     glEnable(GL_LIGHTING);
  209.     glEnable(GL_DEPTH_TEST);
  210.  
  211.     setCheckTexture();
  212.     glEnable(GL_TEXTURE_2D);
  213.  
  214.     glEnable(GL_CULL_FACE);
  215. }
  216.  
  217. void
  218. doRedraw(void)
  219. {
  220.     static GLfloat x, y, z;
  221.  
  222.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  223.  
  224.     glPushMatrix();
  225.     glRotatef(x, 1.0F, 0.0F, 0.0F);
  226.     glRotatef(y, 0.0F, 1.0F, 0.0F);
  227.     glRotatef(z, 0.0F, 0.0F, 1.0F);
  228.  
  229.     drawTorus();
  230.  
  231.     glPopMatrix();
  232.  
  233.     SwapBuffers(hDC);
  234.  
  235.     x += 5.0F;
  236.     if (x > 360.0F) x -= 360.0F;
  237.     y += 7.0F;
  238.     if (y > 360.0F) y -= 360.0F;
  239.     z += 9.0F;
  240.     if (z > 360.0F) z -= 360.0F;
  241. }
  242.  
  243. void
  244. redraw(void)
  245. {
  246.     idleFunc = doRedraw;
  247. }
  248.  
  249. void
  250. resize(void)
  251. {
  252.     setProjection();
  253.     glViewport(0, 0, winWidth, winHeight);
  254. }
  255.  
  256. /*****************************************************************/
  257.  
  258. void
  259. setupPalette(HDC hDC)
  260. {
  261.     PIXELFORMATDESCRIPTOR pfd;
  262.     LOGPALETTE* pPal;
  263.     int pixelFormat = GetPixelFormat(hDC);
  264.     int paletteSize;
  265.  
  266.     DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  267.  
  268.     /*
  269.     ** Determine if a palette is needed and if so what size.
  270.     */
  271.     if (pfd.dwFlags & PFD_NEED_PALETTE ||
  272.         pfd.iPixelType == PFD_TYPE_COLORINDEX) {
  273.     paletteSize = 1 << pfd.cColorBits;
  274.     if (paletteSize > 4096) {
  275.         paletteSize = 4096;
  276.     }
  277.     } else {
  278.     return;
  279.     }
  280.  
  281.     pPal = (LOGPALETTE*)
  282.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  283.     pPal->palVersion = 0x300;
  284.     pPal->palNumEntries = paletteSize;
  285.  
  286.     /*
  287.     ** Fill the logical palette with color ramps.
  288.     **
  289.     ** Set up the logical palette so that it can be realized
  290.     ** into the system palette as an identity palette.
  291.     **
  292.     ** 1) The default static entries should be present and at the right
  293.     **    location.  The easiest way to do this is to grab them from
  294.     **    the current system palette.
  295.     **
  296.     ** 2) All non-static entries should be initialized to unique values.
  297.     **    The easiest way to do this is to ensure that all of the non-static
  298.     **    entries have the PC_NOCOLLAPSE flag bit set.
  299.     */
  300.     {
  301.     int numRamps = NUM_COLORS;
  302.     int rampSize = (paletteSize - 20) / numRamps;
  303.     int extra = (paletteSize - 20) - (numRamps * rampSize);
  304.     int i, r;
  305.  
  306.     /*
  307.     ** Initialize static entries by copying them from the
  308.     ** current system palette.
  309.     */
  310.     GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  311.  
  312.     /*
  313.     ** Fill in non-static entries with desired colors.
  314.     */
  315.     for (r=0; r<numRamps; ++r) {
  316.         int rampBase = r * rampSize + 10;
  317.         PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
  318.         int diffSize = (int) (rampSize * colors[r].ratio);
  319.         int specSize = rampSize - diffSize;
  320.  
  321.         for (i=0; i<rampSize; ++i) {
  322.         GLfloat *c0, *c1;
  323.         GLint a;
  324.  
  325.         if (i < diffSize) {
  326.             c0 = colors[r].amb;
  327.             c1 = colors[r].diff;
  328.             a = (i * 255) / (diffSize - 1);
  329.         } else {
  330.             c0 = colors[r].diff;
  331.             c1 = colors[r].spec;
  332.             a = ((i - diffSize) * 255) / (specSize - 1);
  333.         }
  334.  
  335.         pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]);
  336.         pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]);
  337.         pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]);
  338.         pe[i].peFlags = PC_NOCOLLAPSE;
  339.         }
  340.  
  341.         colors[r].indexes[0] = rampBase;
  342.         colors[r].indexes[1] = rampBase + (diffSize-1);
  343.         colors[r].indexes[2] = rampBase + (rampSize-1);
  344.     }
  345.  
  346.     /*
  347.     ** Initialize any remaining non-static entries.
  348.     */
  349.     for (i=0; i<extra; ++i) {
  350.         int index = numRamps*rampSize+10+i;
  351.         PALETTEENTRY *pe = &pPal->palPalEntry[index];
  352.  
  353.         pe->peRed = (BYTE) 0;
  354.         pe->peGreen = (BYTE) 0;
  355.         pe->peBlue = (BYTE) 0;
  356.         pe->peFlags = PC_NOCOLLAPSE;
  357.     }
  358.     }
  359.  
  360.     hPalette = CreatePalette(pPal);
  361.     free(pPal);
  362.  
  363.     if (hPalette) {
  364.     SelectPalette(hDC, hPalette, FALSE);
  365.     RealizePalette(hDC);
  366.     }
  367. }
  368.  
  369. void
  370. setupPixelFormat(HDC hDC)
  371. {
  372.     PIXELFORMATDESCRIPTOR pfd = {
  373.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  374.     1,                /* version num */
  375.     PFD_DRAW_TO_WINDOW |        /* support window */
  376.     PFD_SUPPORT_OPENGL |        /* support OpenGL */
  377.     PFD_DOUBLEBUFFER,        /* support double-buffering */
  378.     PFD_TYPE_COLORINDEX,        /* color index mode */
  379.     8,                /* 8-bit color depth */
  380.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  381.     0,                /* no alpha buffer */
  382.     0,                /* alpha bits (ignored) */
  383.     0,                /* no accumulation buffer */
  384.     0, 0, 0, 0,            /* accum bits (ignored) */
  385.     16,                /* depth buffer */
  386.     0,                /* no stencil buffer */
  387.     0,                /* no auxiliary buffers */
  388.     PFD_MAIN_PLANE,            /* main layer */
  389.     0,                /* reserved */
  390.     0, 0, 0,            /* no layer, visible, damage masks */
  391.     };
  392.     int SelectedPixelFormat;
  393.     BOOL retVal;
  394.  
  395.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  396.     if (SelectedPixelFormat == 0) {
  397.     MessageBox(WindowFromDC(hDC),
  398.         "ChoosePixelFormat failed\n"
  399.         "This application works best with an 8-bit\n"
  400.         "(256 color) display mode\n",
  401.         "Error",
  402.         MB_ICONERROR | MB_OK);
  403.     exit(1);
  404.     }
  405.  
  406.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  407.     if (retVal != TRUE) {
  408.     MessageBox(WindowFromDC(hDC), "SetPixelFormat failed", "Error",
  409.         MB_ICONERROR | MB_OK);
  410.     exit(1);
  411.     }
  412. }
  413.  
  414. LRESULT APIENTRY
  415. WndProc(
  416.     HWND hWnd,
  417.     UINT message,
  418.     WPARAM wParam,
  419.     LPARAM lParam)
  420. {
  421.     switch (message) {
  422.     case WM_CREATE:
  423.     /*
  424.     ** Set up for OpenGL rendering.  Bind the rendering context to
  425.     ** the same device context that the palette will be selected into.
  426.     */
  427.     hDC = GetDC(hWnd);
  428.     setupPixelFormat(hDC);
  429.     setupPalette(hDC);
  430.     hGLRC = wglCreateContext(hDC);
  431.     wglMakeCurrent(hDC, hGLRC);
  432.     if (!checkExtension("SGI_index_texture")) {
  433.         char message[1024];
  434.  
  435.         sprintf(message,
  436.         "SGI_index_texture is required by this application\n"
  437.         "but is not supported by the current OpenGL renderer.\n\n"
  438.         "Vendor: %s\nRenderer: %s\nVersion: %s",
  439.         glGetString(GL_VENDOR),
  440.         glGetString(GL_RENDERER),
  441.         glGetString(GL_VERSION));
  442.  
  443.         wglMakeCurrent(NULL, NULL);
  444.         wglDeleteContext(hGLRC);
  445.         hGLRC = NULL;
  446.  
  447.         MessageBox(hWnd, message, "OpenGL Extension Required",
  448.             MB_ICONERROR | MB_OK);
  449.         exit(1);
  450.     }
  451.     init();
  452.     idleFunc = doRedraw;
  453.     return 0;
  454.     case WM_DESTROY:
  455.     /*
  456.     ** Finish OpenGL rendering.
  457.     */
  458.     idleFunc = NULL;
  459.     if (hGLRC) {
  460.         wglMakeCurrent(NULL, NULL);
  461.         wglDeleteContext(hGLRC);
  462.     }
  463.     ReleaseDC(hWnd, hDC);
  464.     PostQuitMessage(0);
  465.     return 0;
  466.     case WM_SIZE:
  467.     if (hGLRC) {
  468.         winWidth = (int) LOWORD(lParam);
  469.         winHeight = (int) HIWORD(lParam);
  470.         resize();
  471.         return 0;
  472.     }
  473.     case WM_PALETTECHANGED:
  474.     /*
  475.     ** Update palette mapping if this *is not* the active window.
  476.     */
  477.     if (hGLRC && hPalette && (HWND) wParam != hWnd) {
  478.         UnrealizeObject(hPalette);
  479.         SelectPalette(hDC, hPalette, FALSE);
  480.         RealizePalette(hDC);
  481.         redraw();
  482.         return 0;
  483.     }
  484.     break;
  485.     case WM_QUERYNEWPALETTE:
  486.     /*
  487.     ** Update palette mapping if this *is* the active window.
  488.     */
  489.     if (hGLRC && hPalette) {
  490.         UnrealizeObject(hPalette);
  491.         SelectPalette(hDC, hPalette, FALSE);
  492.         RealizePalette(hDC);
  493.         redraw();
  494.         return TRUE;
  495.     }
  496.     break;
  497.     case WM_PAINT:
  498.     /*
  499.     ** Update the window.  Don't use the device context returned by
  500.     ** BeginPaint as it won't have the right palette selected into it.
  501.     */
  502.     if (hGLRC) {
  503.         PAINTSTRUCT ps;
  504.  
  505.         BeginPaint(hWnd, &ps);
  506.         redraw();
  507.         EndPaint(hWnd, &ps);
  508.         return 0;
  509.     }
  510.     break;
  511.     case WM_CHAR:
  512.     switch ((int)wParam) {
  513.     case VK_ESCAPE:
  514.         DestroyWindow(hWnd);
  515.         return 0;
  516.     default:
  517.         break;
  518.     }
  519.     break;
  520.     default:
  521.     break;
  522.     }
  523.  
  524.     /* Deal with any unprocessed messages */
  525.     return DefWindowProc(hWnd, message, wParam, lParam);
  526. }
  527.  
  528. int APIENTRY
  529. WinMain(
  530.     HINSTANCE hCurrentInst,
  531.     HINSTANCE hPreviousInst,
  532.     LPSTR lpszCmdLine,
  533.     int nCmdShow)
  534. {
  535.     WNDCLASS wndClass;
  536.     HWND hWnd;
  537.     MSG msg;
  538.  
  539.     /* Define and register a window class */
  540.     wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  541.     wndClass.lpfnWndProc = WndProc;
  542.     wndClass.cbClsExtra = 0;
  543.     wndClass.cbWndExtra = 0;
  544.     wndClass.hInstance = hCurrentInst;
  545.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  546.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  547.     wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  548.     wndClass.lpszMenuName = NULL;
  549.     wndClass.lpszClassName = className;
  550.     RegisterClass(&wndClass);
  551.  
  552.     /* Figure out a default size for the window */
  553.     winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
  554.     winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
  555.  
  556.     /* Create a window of the previously defined class */
  557.     hWnd = CreateWindow(
  558.     className,        /* Window class's name */
  559.     windowName,        /* Title bar text */
  560.     WS_OVERLAPPEDWINDOW |    /* The window's style */
  561.     WS_CLIPCHILDREN |
  562.     WS_CLIPSIBLINGS,
  563.     winX, winY,        /* Position */
  564.     winWidth, winHeight,    /* Size */
  565.     NULL,            /* Parent window's handle */
  566.     NULL,            /* Menu handle */
  567.     hCurrentInst,        /* Instance handle */
  568.     NULL);            /* No additional data */
  569.  
  570.     /* Map the window to the screen */
  571.     ShowWindow(hWnd, nCmdShow);
  572.  
  573.     /* Force the window to repaint itself */
  574.     UpdateWindow(hWnd);
  575.  
  576.     /* Process Messages */
  577.     while (1) {
  578.     /* execute the idle function while there are no messages to process */
  579.     while (idleFunc &&
  580.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  581.     {
  582.         (*idleFunc)();
  583.     }
  584.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  585.         break;
  586.     }
  587.     TranslateMessage(&msg);
  588.     DispatchMessage(&msg);
  589.     }
  590.  
  591.     return msg.wParam;
  592. }
  593.  
  594. 
  595.